<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
	<head>
	        <!-- charset must remain utf-8 to be handled properly by Processing -->
		<meta http-equiv="content-type" content="text/html; charset=utf-8" />
		
		<title>P019_WIRES_LIGHTING : Built with Processing</title>
		
		<style type="text/css">
		/* <![CDATA[ */
	
		body {
  		  margin: 60px 0px 0px 55px;
		  font-family: verdana, geneva, arial, helvetica, sans-serif; 
		  font-size: 11px; 
		  background-color: #ddddcc; 
		  text-decoration: none; 
		  font-weight: normal; 
		  line-height: normal; 
		}
		 
		a          { color: #3399cc; }
		a:link     { color: #3399cc; text-decoration: underline; }
		a:visited  { color: #3399cc; text-decoration: underline; }
		a:active   { color: #3399cc; text-decoration: underline; }
		a:hover    { color: #3399cc; text-decoration: underline; }
	
		/* ]]> */
		</style>
	 
	</head>
	<body>
		<div id="content">
			<div id="P019_WIRES_LIGHTING_container">
			
			<!--[if !IE]> -->
				<object classid="java:P019_WIRES_LIGHTING.class" 
            			type="application/x-java-applet"
            			archive="P019_WIRES_LIGHTING.jar"
            			width="100" height="100"
            			standby="Loading Processing software..." >
            			
					<param name="archive" value="P019_WIRES_LIGHTING.jar" />
				
					<param name="mayscript" value="true" />
					<param name="scriptable" value="true" />
				
					<param name="image" value="loading.gif" />
					<param name="boxmessage" value="Loading Processing software..." />
					<param name="boxbgcolor" value="#FFFFFF" />
				
					<param name="test_string" value="outer" />
			<!--<![endif]-->
				
				<object classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93" 
						codebase="http://java.sun.com/update/1.5.0/jinstall-1_5_0_15-windows-i586.cab"
						width="100" height="100"
						standby="Loading Processing software..."  >
						
					<param name="code" value="P019_WIRES_LIGHTING" />
					<param name="archive" value="P019_WIRES_LIGHTING.jar" />
					
					<param name="mayscript" value="true" />
					<param name="scriptable" value="true" />
					
					<param name="image" value="loading.gif" />
					<param name="boxmessage" value="Loading Processing software..." />
					<param name="boxbgcolor" value="#FFFFFF" />
					
					<param name="test_string" value="inner" />
					
					<p>
						<strong>
							This browser does not have a Java Plug-in.
							<br />
							<a href="http://www.java.com/getjava" title="Download Java Plug-in">
								Get the latest Java Plug-in here.
							</a>
						</strong>
					</p>
				
				</object>
				
			<!--[if !IE]> -->
				</object>
			<!--<![endif]-->
			
			</div>
			
			<p>
			int fillR=127,fillG=127,fillB=127;                //FOR INTERACTIVE CHANGES IN COLOR
String data[];
String line1[];
int xRes,yRes;
float pM[],uM[],vM[],nM[];
float near,far,top,bottom,left,right;
int r[],g[],b[];
float rx[],ry[],rz[],sx[],sy[],sz[],tx[],ty[],tz[];
String fileName[];
String sffName[];
float objectS[][][][],objectD[][][][];            //OBJECT 2BE S_tored & D_rawn 
int nFile=4,activeFile=0;
int nSff,nMesh[],nV[][],meshXmid,meshYmid,meshZmid;

//TRANSFORMATION MATRIXES
float rotateMatrixX[][];
float rotateMatrixY[][];
float rotateMatrixZ[][];
float scaleMatrix[][];
float transMatrix[][];
float camMatrix[][];
float projMatrix[][];

//Z-BUFFER AND COLOR BUFFER
int zBuf[][];
color cBuf[][];

//LIGHTING VARIABLES
int AMBIENTi=0,DIFFUSEi=1,SPECULARi=2,POSITIONi=3;
float specularN=1;
int Xi=0,Yi=1,Zi=2,Wi=3;
int Ri=0,Gi=1,Bi=2;
float Light[][][];//Light[id][{Type},{Position}][{Ambient,Diffuse,Specular},{X,Y,Z,W}]
float DifComp[];//foreach light source I need a diffuse component to be calculated before the polygon
//goes for rendering
int ActiveLights[],numOfLights=5,numOfActiveLights=0,selectedLight=0;
boolean[] AMBIENTon = new boolean[numOfLights],DIFFUSEon = new boolean[numOfLights],SPECULARon = new boolean[numOfLights];
boolean showLightSources=true;

//STORAGE VARIABLES TO BE ABLE TO RASTER POLYGONS OF THE OBJECT TO DRAW
float myMesh[][];//point storage
color myColor;
int pCntr;//point counter

//ALL OTHER INTERACTIVITY VARIABLES
int selectedObject=0,selectedTextArea=0;
int textArea[][],meshTextArea[][][];
String warningText = new String("To see light-effects switch to lighting mode.[Click the text below or press '3']");;
int projectionMode[];//Projection=1,Orthogonal=0;
int drawMode=0;//0 simple/1 zBuffer on/2 backface culling/3 triangulate on
boolean numDisplay=false,moveLight=false;
int drawWireFrames=1;//0 no wires, 1 simple wires, 2 antialiased wires
int selectedColor=0;
int time=0;
float timeInc=5;
boolean timeIncrease=false;
void DogaCopyMatrix(float[] from,float[] to,int n){
int i=0;
for (i=0;i<n;i++) to[i]=from[i];
return;
}
void DogaCopyMatrix2(float[][] from,float[][] to,int row,int col){
int i=0,j=0;
for (i=0;i<row;i++)
for(j=0;j<col;j++)
to[i][j]=from[i][j];
return;
}
void DogaMatMult(float matA[][],float matB[][],int A,int B,int C){
float temp[][];
int i,j,k;
temp = new float[C][A];
for (i=0;i<C;i++)
for(k=0;k<B;k++)
temp[i][k] = 0;
for (i=0;i<C;i++)
for (j=0;j<A;j++)
for(k=0;k<B;k++)
temp[i][j] += matA[j][k]*matB[i][k];
for (i=0;i<C;i++)
for (j=0;j<B;j++)
matB[i][j] = temp[i][j];
return;
}
float DogaDotProduct(float V1[],float V2[]) {return V1[0]*V2[0]+V1[1]*V2[1]+V1[2]*V2[2];}
float[] DogaCrossProduct(float V1[],float V2[]) {
float m;
float[] Vn=new float[4];
Vn[0] = V1[1]*V2[2] - V2[1]*V1[2];
Vn[1] = V2[0]*V1[2] - V1[0]*V2[2];
Vn[2] = V1[0]*V2[1] - V2[0]*V1[1];
Vn[3] = 1;
m = sqrt(DogaDotProduct(Vn,Vn));
for (int i=0;i<3;i++)
Vn[i] = Vn[i]/m;
return Vn;
}
void DogaMakeUnitVector(float V[]) {
float w=0;
w = sqrt(DogaDotProduct(V,V));
V[0] = V[0]/w;
V[1] = V[1]/w;
V[2] = V[2]/w;
}
void DogaRotateFX(float degX,float degY,float degZ) {
rotateMatrixX = new float[][]{{1,0,0,0},
		 {0,cos(degX),-sin(degX),0},
		 {0,sin(degX),cos(degX),0},
		 {0,0,0,1}
		                };
rotateMatrixY = new float[][]{{cos(degY),0,sin(degY),0},
		{0,1,0,0},
		{-sin(degY),0,cos(degY),0},
		{0,0,0,1}
		        };
rotateMatrixZ = new float[][]{{cos(degZ),-sin(degZ),0,0},
		{sin(degZ),cos(degZ),0,0},
		{0,0,1,0},
		{0,0,0,1}
	    	               };
return;
}

void DogaScaleFX(float sizeX,float sizeY,float sizeZ) {
scaleMatrix = new float[][]{{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}};
scaleMatrix[0][0] = sizeX;
scaleMatrix[1][1] = sizeY;
scaleMatrix[2][2] = sizeZ;
return;
}
void DogaTranslateFX(float X,float Y,float Z) {
transMatrix = new float[][]{{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}};
transMatrix[0][3] = X;
transMatrix[1][3] = Y;
transMatrix[2][3] = Z;
return;
}
void DogaCameraFX(float r[],float u[],float v[],float n[]) {
camMatrix = new float[][]{{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}};
DogaCopyMatrix(u,camMatrix[0],4);
DogaCopyMatrix(v,camMatrix[1],4);
DogaCopyMatrix(n,camMatrix[2],4);
camMatrix[0][3] = -DogaDotProduct(r,u);
camMatrix[1][3] = -DogaDotProduct(r,v);
camMatrix[2][3] = -DogaDotProduct(r,n);
return;
}
void DogaProjectionFX(int projMode,float Near,float Far,float Top,float Bottom,float Left,float Right) {
projMatrix = new float[][]{{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}};
if ((Right==Left)||(Top==Bottom)||(Far==Near)) return;
if (projMode==0) {//ORTHOGONAL
projMatrix[0][0] = (float)2/(Right-Left);
projMatrix[0][3] = -(float)(Right+Left)/(Right-Left);
projMatrix[1][1] = (float)2/(Top-Bottom);
projMatrix[1][3] = -(float)(Top+Bottom)/(Top-Bottom);
projMatrix[2][2] = -(float)2/(Far-Near);
projMatrix[2][3] = -(float)(Far+Near)/(Far-Near);
projMatrix[3][3] = 1;
}
else if (projMode==1) {//FRUSTUM
projMatrix[0][0] = (float)2*Near/(Right-Left);
projMatrix[0][2] = (float)(Right+Left)/(Right-Left);
projMatrix[1][1] = (float)2*Near/(Top-Bottom);
projMatrix[1][2] = (float)(Top+Bottom)/(Top-Bottom);
projMatrix[2][2] = -(float)(Far+Near)/(Far-Near);
projMatrix[2][3] = -(float)(2*Far*Near)/(Far-Near);
projMatrix[3][2] = -1;
projMatrix[3][3] = 0;    
}
return;
}
float winX(float x) {
return (x+1)*((xRes-1)/2);
}
float winY(float y) {
return yRes-(y+1)*((yRes-1)/2);
}
//FOR ANALYZING THE MESH TO DRAW ACCORDING TO THE DRAWTYPE(SIMPLE,Z-BUFFER,BACKFACECULLING,LIGHTING)
void DogaSetMesh(int pNum,int x,int y,float z,int R,int G,int B,int W) {
if (pNum==0) {//the first point of the mesh
myMesh = new float[10][4];
myColor = color(R,G,B,W);
meshXmid=0; meshYmid=0; meshZmid=0;
pCntr=0;
}
myMesh[pCntr][0] = x; meshXmid+=x;
myMesh[pCntr][1] = y; meshYmid+=y;
myMesh[pCntr][2] = z; meshZmid+=z;
pCntr++;
}
void ApplyMatrix(int objectID) {
//FOR CHANGING THE VALUES OF THE OBJECT TO BE DRAWN BY CHANGING THE SOURCE OBJECT POINTS
int i=0,j=0,k=0;
i=objectID;
DogaRotateFX(rx[i],ry[i],rz[i]);
DogaScaleFX(sx[i],sy[i],sz[i]);
DogaTranslateFX(tx[i],ty[i],tz[i]);
for (j=0;j<nMesh[i];j++) {
DogaCopyMatrix2(objectS[i][j],objectD[i][j],nV[i][j],4);
DogaMatMult(rotateMatrixX,objectD[i][j],4,4,nV[i][j]);
DogaMatMult(rotateMatrixY,objectD[i][j],4,4,nV[i][j]);
DogaMatMult(rotateMatrixZ,objectD[i][j],4,4,nV[i][j]);
DogaMatMult(scaleMatrix,objectD[i][j],4,4,nV[i][j]);
DogaMatMult(transMatrix,objectD[i][j],4,4,nV[i][j]);      
DogaMatMult(camMatrix,objectD[i][j],4,4,nV[i][j]);
DogaMatMult(projMatrix,objectD[i][j],4,4,nV[i][j]);
for (k=0;k<nV[i][j];k++) {// now read every point in mesh
objectD[i][j][k][0] = winX(objectD[i][j][k][0]/objectD[i][j][k][3]);
objectD[i][j][k][1] = winY(objectD[i][j][k][1]/objectD[i][j][k][3]);
objectD[i][j][k][2] = 100*(objectD[i][j][k][2]/objectD[i][j][k][3]);
}//k-nV
}//j-nMesh
}
void setup() {
int i=0,j=0;
Light = new float[numOfLights][4][4];
DifComp = new float[numOfLights];
ActiveLights = new int[numOfLights];
fileName = new String[]{"scene.txt","scene2.txt","scene3.txt","scene4.txt"};
readInBasicFile();  
size(xRes,yRes);
background(0,50,100);
PFont myFont = createFont("verdana", 12);
textFont(myFont);
setTextAreaValues();
ResetLights();
}
void draw() {
background(0,50,100);

if (timeIncrease) time+=timeInc;
else time-=timeInc;
if ((time>255)&&(timeIncrease)) timeIncrease=false;
else if ((!timeIncrease)&&(time<1)) timeIncrease=true;

if (drawMode!=0) DogaClearZBuffer();
drawPoints();
if (drawMode!=0) DogaDisplayZBuffer();
drawText();
drawLightSource();
}
void drawPoints() {
int i=0,j=0,k=0;
for (i=0;i<nSff;i++) {
stroke(r[i],g[i],b[i]);
for (j=0;j<nMesh[i];j++){
for(k=0;k<nV[i][j]-1;k++){
if ((drawMode==2)||(drawMode==3)) DogaSetMesh(k,int(objectD[i][j][k][0]),int(objectD[i][j][k][1]),objectD[i][j][k][2],r[i],g[i],b[i],255);
else {
drawDogaLineRGB(int(objectD[i][j][k][0]),int(objectD[i][j][k][1]),objectD[i][j][k][2],
int(objectD[i][j][k+1][0]),int(objectD[i][j][k+1][1]),objectD[i][j][k+1][2],
r[i],g[i],b[i],255);
}
}
if ((drawMode==2)||(drawMode==3)) {
DogaSetMesh(k,int(objectD[i][j][k][0]),int(objectD[i][j][k][1]),objectD[i][j][k][2],r[i],g[i],b[i],255);
DogaDrawMesh(nV[i][j],i,j);
}
else {
drawDogaLineRGB(int(objectD[i][j][k][0]),int(objectD[i][j][k][1]),objectD[i][j][k][2],
int(objectD[i][j][0][0]),int(objectD[i][j][0][1]),objectD[i][j][0][2],
r[i],g[i],b[i],255);
}
}
}
}
void DogaClearZBuffer() {
for (int i=0;i<xRes;i++)
for (int j=0;j<yRes;j++) {
zBuf[i][j] = +1000000;
cBuf[i][j] = color(0,50,100);
}
}
void DogaDisplayZBuffer() {
for (int i=0;i<xRes;i++)
for (int j=0;j<yRes;j++) {
stroke(cBuf[i][j]);
point(i,j);
}
}
void DogaSetPixel(float x,float y, float z, color c) {
int i=int(x),j=int(y);
if ((i<0)||(i>width-1)||(j<0)||(j>height-1)) return;
if (int(z)>zBuf[i][j]) return;
zBuf[i][j] = int(z);
cBuf[i][j] = c;
}
void DogaSetPixelLight(float x,float y, float z,int Rc,int Gc,int Bc,float[] Nv) {
int i=int(x),j=int(y),k=0,ambM=0,difM=0,specM=0;
int Ra=0,Ga=0,Ba=0,Rd=0,Gd=0,Bd=0,Rs=0,Gs=0,Bs=0;
float Ka=1,Kd=1,Ks=1;
float[] SpecComp = new float[1];
if ((i<0)||(i>width-1)||(j<0)||(j>height-1)) return;
if (int(z)>zBuf[i][j]) return;

k=0;
while (k<numOfLights) {
if (ActiveLights[k]==1) {
if (AMBIENTon[k]) {
ambM++;
Ra += Light[k][AMBIENTi][Ri]*Ka*(Light[k][AMBIENTi][Wi]/255);
Ga += Light[k][AMBIENTi][Gi]*Ka*(Light[k][AMBIENTi][Wi]/255);
Ba += Light[k][AMBIENTi][Bi]*Ka*(Light[k][AMBIENTi][Wi]/255);
}
if (DIFFUSEon[k]) {
difM++;
Rd += Light[k][DIFFUSEi][Ri]*Kd*DifComp[k]*(Light[k][DIFFUSEi][Wi]/255);
Gd += Light[k][DIFFUSEi][Gi]*Kd*DifComp[k]*(Light[k][DIFFUSEi][Wi]/255);
Bd += Light[k][DIFFUSEi][Bi]*Kd*DifComp[k]*(Light[k][DIFFUSEi][Wi]/255);
}
if (SPECULARon[k]) {
specM++;
ComputeSpecularVector(SpecComp,i,j,int(z),k,Nv);
Rs += Light[k][SPECULARi][Ri]*Ks*pow(SpecComp[0],1+20*(Light[k][SPECULARi][Wi]/255));
Gs += Light[k][SPECULARi][Gi]*Ks*pow(SpecComp[0],1+20*(Light[k][SPECULARi][Wi]/255));
Bs += Light[k][SPECULARi][Bi]*Ks*pow(SpecComp[0],1+20*(Light[k][SPECULARi][Wi]/255));
}
}
k++;
}
k=1;
if (ambM==0) ambM=1;//not to have division by zero
else k++;
if (difM==0) difM=1;//not to have division by zero
else k++;
if (specM==0) specM=1;//not to have division by zero
else k++;

Ra/=ambM; Ga/=ambM; Ba/=ambM;
Rd/=difM; Gd/=difM; Bd/=difM;
Rs/=specM; Gs/=specM; Bs/=specM;

zBuf[i][j] = int(z);
cBuf[i][j] = color((Rc+Ra+Rd+Rs)/k,(Gc+Ga+Gd+Gs)/k,(Bc+Ba+Bd+Bs)/k);
}
void drawLightSource() {
int k=0;
if (!showLightSources) return;
stroke(255,0,0);
fill(255,0,0);
float Line=10;
rectMode(CORNER);
stroke(255,0,0);
fill(255,255,255);
while (k<numOfLights) {
if (ActiveLights[k]==1) {
Line = 10-Light[k][POSITIONi][Zi]*0.01;
rect(Light[k][POSITIONi][Xi],Light[k][POSITIONi][Yi],Line,Line);      
text("L"+k,Light[k][POSITIONi][Xi],Light[k][POSITIONi][Yi]);
}
k++;
}
}
void ResetLights() {
numOfActiveLights=0;
selectedLight=0;
for (int i=0;i<numOfLights;i++) {
ActiveLights[i] = 0;
AMBIENTon[i]=true;
DIFFUSEon[i]=true;
SPECULARon[i]=true;
DifComp[i] = 0;
//Light ID=i
//AmbientLight
Light[i][AMBIENTi][Ri] = 127;
Light[i][AMBIENTi][Gi] = 127;
Light[i][AMBIENTi][Bi] = 127;
Light[i][AMBIENTi][Wi] = 255;
//DiffuseLight
Light[i][DIFFUSEi][Ri] = 127;
Light[i][DIFFUSEi][Gi] = 127;
Light[i][DIFFUSEi][Bi] = 127;
Light[i][DIFFUSEi][Wi] = 255;
//SpecularLight
Light[i][SPECULARi][Ri] = 127;
Light[i][SPECULARi][Gi] = 127;
Light[i][SPECULARi][Bi] = 127;
Light[i][SPECULARi][Wi] = 50;
//Position
Light[i][POSITIONi][Xi] = xRes/2;
Light[i][POSITIONi][Yi] = yRes/2;
Light[i][POSITIONi][Zi] = 0;
Light[i][POSITIONi][Wi] = 1;
}
AMBIENTon[0]=true;
DIFFUSEon[0]=true;
SPECULARon[0]=true;
//Light ID=0
//AmbientLight
Light[0][AMBIENTi][Ri] = 0;
Light[0][AMBIENTi][Gi] = 255;
Light[0][AMBIENTi][Bi] = 255;
Light[0][AMBIENTi][Wi] = 255;
//DiffuseLight
Light[0][DIFFUSEi][Ri] = 255;
Light[0][DIFFUSEi][Gi] = 0;
Light[0][DIFFUSEi][Bi] = 255;
Light[0][DIFFUSEi][Wi] = 255;
//SpecularLight
Light[0][SPECULARi][Ri] = 0;
Light[0][SPECULARi][Gi] = 255;
Light[0][SPECULARi][Bi] = 247;
Light[0][SPECULARi][Wi] = 255;
//Position
Light[0][POSITIONi][Xi] = 337;
Light[0][POSITIONi][Yi] = 239;
Light[0][POSITIONi][Zi] = -50;
Light[0][POSITIONi][Wi] = 1;

AMBIENTon[1]=true;
DIFFUSEon[1]=false;
SPECULARon[1]=true;
//Light ID=1
//AmbientLight
Light[1][AMBIENTi][Ri] = 0;
Light[1][AMBIENTi][Gi] = 255;
Light[1][AMBIENTi][Bi] = 255;
Light[1][AMBIENTi][Wi] = 255;
//DiffuseLight
Light[1][DIFFUSEi][Ri] = 255;
Light[1][DIFFUSEi][Gi] = 0;
Light[1][DIFFUSEi][Bi] = 255;
Light[1][DIFFUSEi][Wi] = 255;
//SpecularLight
Light[1][SPECULARi][Ri] = 0;
Light[1][SPECULARi][Gi] = 255;
Light[1][SPECULARi][Bi] = 247;
Light[1][SPECULARi][Wi] = 73;
//Position
Light[1][POSITIONi][Xi] = 250;
Light[1][POSITIONi][Yi] = 212;
Light[1][POSITIONi][Zi] = -96;
Light[1][POSITIONi][Wi] = 1;

AMBIENTon[2]=false;
DIFFUSEon[2]=false;
SPECULARon[2]=true;
//Light ID=1
//AmbientLight
Light[2][AMBIENTi][Ri] = 127;
Light[2][AMBIENTi][Gi] = 255;
Light[2][AMBIENTi][Bi] = 255;
Light[2][AMBIENTi][Wi] = 255;
//DiffuseLight
Light[2][DIFFUSEi][Ri] = 127;
Light[2][DIFFUSEi][Gi] = 255;
Light[2][DIFFUSEi][Bi] = 255;
Light[2][DIFFUSEi][Wi] = 255;
//SpecularLight
Light[2][SPECULARi][Ri] = 255;
Light[2][SPECULARi][Gi] = 255;
Light[2][SPECULARi][Bi] = 255;
Light[2][SPECULARi][Wi] = 60;
//Position
Light[2][POSITIONi][Xi] = 308;
Light[2][POSITIONi][Yi] = 284;
Light[2][POSITIONi][Zi] = 63;
Light[2][POSITIONi][Wi] = 1;

AMBIENTon[3]=true;
DIFFUSEon[3]=true;
SPECULARon[3]=true;
//Light ID=3
//AmbientLight
Light[3][AMBIENTi][Ri] = 0;
Light[3][AMBIENTi][Gi] = 255;
Light[3][AMBIENTi][Bi] = 255;
Light[3][AMBIENTi][Wi] = 255;
//DiffuseLight
Light[3][DIFFUSEi][Ri] = 255;
Light[3][DIFFUSEi][Gi] = 0;
Light[3][DIFFUSEi][Bi] = 255;
Light[3][DIFFUSEi][Wi] = 255;
//SpecularLight
Light[3][SPECULARi][Ri] = 0;
Light[3][SPECULARi][Gi] = 255;
Light[3][SPECULARi][Bi] = 247;
Light[3][SPECULARi][Wi] = 255;
//Position
Light[3][POSITIONi][Xi] = 261;
Light[3][POSITIONi][Yi] = 291;
Light[3][POSITIONi][Zi] = 44;
Light[3][POSITIONi][Wi] = 1;

AMBIENTon[4]=true;
DIFFUSEon[4]=true;
SPECULARon[4]=true;
//Light ID=4
//AmbientLight
Light[4][AMBIENTi][Ri] = 0;
Light[4][AMBIENTi][Gi] = 255;
Light[4][AMBIENTi][Bi] = 255;
Light[4][AMBIENTi][Wi] = 255;
//DiffuseLight
Light[4][DIFFUSEi][Ri] = 255;
Light[4][DIFFUSEi][Gi] = 0;
Light[4][DIFFUSEi][Bi] = 255;
Light[4][DIFFUSEi][Wi] = 255;
//SpecularLight
Light[4][SPECULARi][Ri] = 0;
Light[4][SPECULARi][Gi] = 255;
Light[4][SPECULARi][Bi] = 247;
Light[4][SPECULARi][Wi] = 255;
//Position
Light[4][POSITIONi][Xi] = 340;
Light[4][POSITIONi][Yi] = 191;
Light[4][POSITIONi][Zi] = -148;
Light[4][POSITIONi][Wi] = 1;
}
void ComputeDiffuseVector(float xP,float yP,float zP,float[] N) {
float[] L = new float[3];
int k=0;
//first determine L as the Ligth vector
while (k<numOfLights) {
if ((ActiveLights[k]==1)&&(DIFFUSEon[k])) {
L[Xi] = Light[k][POSITIONi][Xi] - xP;
L[Yi] = Light[k][POSITIONi][Yi] - yP;
L[Zi] = Light[k][POSITIONi][Zi] - zP;
DogaMakeUnitVector(L);
DifComp[k] = DogaDotProduct(N,L);
}
k++;
}
}
void ComputeSpecularVector(float SpecComp[],float xP,float yP,float zP,int LightID,float[] N) {
float[] L = new float[3];
int i=0;
//first determine L as the Ligth vector
L[Xi] = Light[LightID][POSITIONi][Xi] - xP;
L[Yi] = Light[LightID][POSITIONi][Yi] - yP;
L[Zi] = Light[LightID][POSITIONi][Zi] - zP;
DogaMakeUnitVector(L);
SpecComp[0] = DogaDotProduct(N,L);
}
void DogaDrawMesh(int n,int objNum,int polyNum) {
int k=0,difZ=2;
float[] V1=new float[4];
float[] V2=new float[4];
float[] V3=new float[4];
V1[0] = myMesh[1][0] - myMesh[0][0];
V1[1] = myMesh[1][1] - myMesh[0][1];
V1[2] = myMesh[1][2] - myMesh[0][2];
V1[3] = 1;
V2[0] = myMesh[n-1][0] - myMesh[0][0];
V2[1] = myMesh[n-1][1] - myMesh[0][1];
V2[2] = myMesh[n-1][2] - myMesh[0][2];
V2[3] = 1;
DogaMakeUnitVector(V1);
DogaMakeUnitVector(V2);
V3 = DogaCrossProduct(V1,V2);
if ((V3[2]>0)&&(objNum==selectedObject)) {
meshTextArea[selectedObject][polyNum][0] = 0;
meshTextArea[selectedObject][polyNum][1] = 0;
meshTextArea[selectedObject][polyNum][2] = -1;
return;
}
meshXmid /= n; meshYmid /= n; meshZmid /= n;
//Compute Diffuse Component Before Going To Render
if (drawMode==3) {
ComputeDiffuseVector(meshXmid,meshYmid,meshZmid,V3);
DogaTriangulateAndRaster(myMesh,n,myColor,polyNum,V3);
}
if (drawWireFrames!=0) {
for(k=0;k<n-1;k++)
drawDogaLineCOL(int(myMesh[k][0]),int(myMesh[k][1]),myMesh[k][2]-difZ,
int(myMesh[k+1][0]),int(myMesh[k+1][1]),myMesh[k+1][2]-difZ,
myColor);
drawDogaLineCOL(int(myMesh[k][0]),int(myMesh[k][1]),myMesh[k][2]-difZ,
int(myMesh[0][0]),int(myMesh[0][1]),myMesh[0][2]-difZ,
myColor);
}
if (objNum==selectedObject) {
meshTextArea[selectedObject][polyNum][0] = meshXmid;
meshTextArea[selectedObject][polyNum][1] = meshYmid;
meshTextArea[selectedObject][polyNum][2] = 1;
}
}
void DogaTriangulateAndRaster(float[][] vList,int n,color col,int polyNum,float[] Nv) {
int i=0,j=0,k=0,a=0,b=0,c=0;
int maxInc=0;
if (n>15) return;
if (n==2) {
drawDogaLineCOL(int(vList[0][0]),int(vList[0][1]),vList[0][2],
int(vList[1][0]),int(vList[1][1]),vList[1][2],
col);
return;
}
if (n==3) {
DogaRasterTriangle(vList[0],vList[1],vList[2],col,polyNum,Nv);
return;
}
if (n==4) maxInc=2;
else if (n<=8) maxInc=4;
else maxInc=8;

for(i=2;i<=maxInc;i*=2){
j=0;
while(j<n) {
a=j; b=j+i/2; c=j+i;
if ((b>=n)&&(c>=n)) j=n+1;
else {
if (c>=n) c=0;
DogaRasterTriangle(vList[a],vList[b],vList[c],col,polyNum,Nv);
}
j+=i;
}
}
}
void DogaRasterTriangle(float[] P0,float[] P1,float[] P2,color c,int polyNum,float[] Nv) {
float P[][] = new float[3][3],Cv1[] = new float[3],Cv2[] = new float[3];
float xInc[]=new float[3],yInc[]=new float[3],zInc[]=new float[3],zRowScale,xRowScale;
float xRowInc[][]=new float[2][2],zRowInc[][]=new float[2][2];

int loopStart[]=new int[2],loopEnd[]=new int[2];
float xRowStart,xRowEnd,zRowStart,zRowEnd;

int i=0,midPoint=1;//midPoint will be 1 or to according to which point has the change of dec/inc
float x=0,y=0,z=0;//for rendering and "for-loop" values

int from=0,to=1,loopN=0;
int fr0to1=0,fr0to2=1,fr1to2=2;

for(i=0;i<3;i++) {
P[0][i] = P0[i];
P[1][i] = P1[i];
P[2][i] = P2[i];
}
SortPoints(P);//P[0] with the highest Y, P1 with a smaller X and P2 with the bigger X

//now check if the triangle is fine for the algorithm to draw.If not make them fine and recursively draw.
Cv1[0] = P[0][0] - P[1][0];//0to1
Cv1[1] = P[1][1] - P[0][1];//0to1  
Cv2[0] = P[2][0] - P[1][0];//2to1
Cv2[1] = P[1][1] - P[2][1];//2to1
if ((Cv2[0]<Cv1[0])&&(P[2][1]<P[1][1]-Cv2[0]*(Cv1[1]/Cv1[0]))) {
//this means the triangle is not fine. so assign new 2 triangles and draw them
Cv1[0] = (P[0][0] + P[1][0])/2;
Cv1[1] = (P[0][1] + P[1][1])/2;
Cv1[2] = (P[0][2] + P[1][2])/2;
DogaRasterTriangle(P[2],P[1],Cv1,c,polyNum,Nv);
DogaRasterTriangle(P[0],P[2],Cv1,c,polyNum,Nv);
return;
}
else if ((P[1][0]>P[0][0])&&(P[1][1]<P[2][1])) {
//this ALSO means the triangle is not fine. so assign new 2 triangles and draw them
Cv1[0] = P[0][0] + ((P[0][1]-P[1][1])/(P[0][1]-P[2][1]))*(P[2][0]-P[0][0]);
Cv1[1] = P[1][1];
Cv1[2] = P[0][2] + ((P[0][1]-P[1][1])/(P[0][1]-P[2][1]))*(P[2][2]-P[0][2]);
DogaRasterTriangle(P[0],P[1],Cv1,c,polyNum,Nv);
DogaRasterTriangle(P[1],P[2],Cv1,c,polyNum,Nv);
return;
}
// FIND THE HEIGHT DIFFERENCES AMONG THE POINTS
if ((P[0][1]-P[1][1])!=0) yInc[0] = -1/(P[0][1]-P[1][1]); else yInc[fr0to1]=0;//0->1
if ((P[0][1]-P[2][1])!=0) yInc[1] = -1/(P[0][1]-P[2][1]); else yInc[fr0to2]=0;//0->2
if ((P[1][1]-P[2][1])!=0) yInc[2] = -1/(P[1][1]-P[2][1]); else yInc[fr1to2]=0;//1->2

//FIND THE X AND Z DIFFERENCES AMONG THE POINTS
xInc[fr0to1] = (P[0][0]-P[1][0])*yInc[fr0to1];//for line 0->1
zInc[fr0to1] = (P[0][2]-P[1][2])*yInc[fr0to1];

xInc[fr0to2] = (P[0][0]-P[2][0])*yInc[fr0to2];//for line 0->2
zInc[fr0to2] = (P[0][2]-P[2][2])*yInc[fr0to2];

xInc[fr1to2] = (P[1][0]-P[2][0])*yInc[fr1to2];//for line 1->2
zInc[fr1to2] = (P[1][2]-P[2][2])*yInc[fr1to2];

loopN=0;
if (yInc[fr0to1]==0) {//the first 2 points are on the same y value
// the first start point is the second point P[1]
xRowStart = P[1][0];
zRowStart = P[1][2];
//no increment for x and z values
//xInc[fr0to1]=zInc[fr0to1]=0;
}
else {// the first two points have different y values, in other words P[1][y]<P[0][y]
// the first start point is the first point P[0]
xRowStart = P[0][0];
zRowStart = P[0][2];
}
// no matter what, the end points will be of P[0]
xRowEnd = P[0][0];
zRowEnd = P[0][2];

//loops will be based on Y values, hence the start point is P[0][1] ->
loopStart[loopN] = int(P[0][1]);
//Row increments for the first run
xRowInc[from][loopN] = xInc[fr0to1];//from
xRowInc[to][loopN]   = xInc[fr0to2];//to
zRowInc[from][loopN] = zInc[fr0to1];//from
zRowInc[to][loopN]	 = zInc[fr0to2];//to
loopN=1;
//P[1][x]<P[2][x] but what about the y values??
if (P[1][1]<P[2][1]) {// so P[1] is at a higher point
//First loop will start with P[0][y] and end with P[1][y]
//Second loop will start with P[1][y]+1 and end with P[2][y]
midPoint          = 1;
loopEnd[0]       = int(P[1][1]);
loopStart[loopN]  = int(P[1][1]+1);
loopEnd[loopN]    = int(P[2][1]);
//Row increments for the second run
xRowInc[from][loopN] = xInc[fr1to2];//from
xRowInc[to][loopN]   = xInc[fr0to2];//to
zRowInc[from][loopN] = zInc[fr1to2];//from
zRowInc[to][loopN]   = zInc[fr0to2];//to
}
else {//P[2] is at a higher point
	//First loop will start with P[0][y] and end with P[2][y]
	//Second loop will start with P[2][y]-1 and end with P[1][y]
midPoint         = 2;
loopEnd[0]       = int(P[2][1]);
loopStart[loopN] = int(P[2][1]+1);
loopEnd[loopN]   = int(P[1][1]);
//Row increments for the second run
xRowInc[from][loopN] = xInc[fr0to1];//from
xRowInc[to][loopN]   = xInc[fr1to2];//to
zRowInc[from][loopN] = zInc[fr0to1];//from
zRowInc[to][loopN]   = zInc[fr1to2];//to
}

for (i=0;i<2;i++) {//there will be 2 runs, "i" will indicate the loop number
y=loopStart[i];
if (i==1) {//this means the inc/dec will change
if (midPoint==1) {xRowStart=P[1][0];zRowStart=P[1][2];}
else {xRowEnd=P[2][0];zRowEnd=P[2][2];}
}
while (y<=loopEnd[i]) {//y will increase for each scan line
z=zRowStart;
//find the increment for z values during the scan line
if ((xRowEnd==xRowStart)&&(zRowEnd==zRowStart)) {xRowScale=1; zRowScale = 0;}//(zRowEnd-zRowStart)/(loopEnd[i]-loopStart[i]);
else if (absD(xRowEnd-xRowStart)>0) zRowScale = (zRowEnd-zRowStart)/(xRowEnd-xRowStart);
else zRowScale = 1/(zRowEnd-zRowStart);
x=xRowStart;
while (x<=xRowEnd) {
DogaSetPixel(x,y,z,color(fillR,fillG,fillB));
if (numOfActiveLights>0) DogaSetPixelLight(x,y,z,fillR,fillG,fillB,Nv);
z = z+zRowScale;
x = x+=1;
}
xRowStart = xRowStart - xRowInc[from][i];
xRowEnd   = xRowEnd   - xRowInc[to][i];
zRowStart = zRowStart - zRowInc[from][i];
zRowEnd   = zRowEnd   - zRowInc[to][i];
y+=1;
}
}
return;
}
void SortPoints(float P[][]){
int i=0,j=0,k=0,ii=0,maxY[]=new int[2];
float x=0,y=0,z=0;
maxY[0]=maxY[1]=height+1;
for(i=0;i<3;i++) {
j=(i+1)%3;
k=(i+2)%3;
if ((P[i][1]<=P[j][1])&&(P[i][1]<=P[k][1])) 
if (ii<1)  maxY[ii++]=i;
}
if ((ii>1)&&(P[maxY[0]][0]>P[maxY[1]][0])) {//so second one will get the values of last one
x = P[0][0];		y = P[0][1];		  z = P[0][2];
P[0][0] = P[maxY[1]][0];	P[0][1] = P[maxY[1]][1];  P[0][2] = P[maxY[1]][2];
P[maxY[1]][0] = x;		P[maxY[1]][1] = y;	  P[maxY[1]][2] = z;
}
else {
x = P[0][0];		y = P[0][1];		  z = P[0][2];
P[0][0] = P[maxY[0]][0];	P[0][1] = P[maxY[0]][1];  P[0][2] = P[maxY[0]][2];
P[maxY[0]][0] = x;		P[maxY[0]][1] = y;	  P[maxY[0]][2] = z;
}
if (P[1][0]>P[2][0]) {//so second one will get the values of last one
x = P[2][0];	y = P[2][1];  	    z = P[2][2];
P[2][0] = P[1][0];	P[2][1] = P[1][1];  P[2][2] = P[1][2];
P[1][0] = x;	P[1][1] = y;	    P[1][2] = z;
}
}
void drawDogaLineRGB(int x0,int y0,float z0,int x1,int y1,float z1,int R,int G,int B,int W) {
int xs,xf,ys,yf;
float zs=0,zf=0,zDif=0,z=0,m=1;
int d=1;
int i,j,k;
// first lets make sure that xf>xs
if (x1>x0) {xs=x0;xf=x1;ys=y0;yf=y1;zs=z0;zf=z1;}
else {xs=x1;xf=x0;ys=y1;yf=y0;zs=z1;zf=z0;}
if (yf<ys) d=-1;

int dx=xf-xs;
int dy=(yf-ys)*d;
int dif=dy-dx;

point(xs,ys);

if (dx>=dy) { // IF X-BASED
i=xs;j=ys;zDif=(zf-zs)/dx;z=zs;
while (i!=xf) {
if (dif>0) {i++;j+=d;dif+=dy-dx;}
else {i++;dif+=dy;}

m=1;
//      m=absD(float(dif/dx));
if (drawMode==0) {//SIMPLE MODE
if (drawWireFrames==1) {stroke(R,G,B,W); point(i,j);}
else if (drawWireFrames==2) {
stroke(R*m,G*m,B*m,W);
point(i,j);
stroke(R*(1-m),G*(1-m),B*(1-m),W); //ANTI-ALIASED COLOR IS THE HALF BRIGHT OF THE SAME COLOR
point(i,j-1);
}
}
else {// OTHER MODES
if (drawWireFrames==1) DogaSetPixel(i,j,z,color(R,G,B,W)); 
else {
DogaSetPixel(i,j,z,color(R*m,G*m,B*m,W)); 
DogaSetPixel(i,j-1,z,color(R*(1-m),G*(1-m),B*(1-m),W)); 
}
}
z+=zDif;
}
}
else { // IF Y-BASED
i=xs;j=ys;zDif=(zf-zs)/dy;z=zs;
while (j!=yf) {
if (dif>0) {i++;j+=d;dif+=dx-dy;}
else {j+=d;dif+=dx;}

m=0.7;
//    m=absD(float(dif/dy));
if (drawMode==0) {//SIMPLE MODE
if (drawWireFrames==1) {stroke(R,G,B,W); point(i,j);}
else if (drawWireFrames==2) {
stroke(R*m,G*m,B*m,W);
point(i,j);
stroke(R*(1-m),G*(1-m),B*(1-m),W); //ANTI-ALIASED COLOR IS THE HALF BRIGHT OF THE SAME COLOR
point(i,j-1);
}
}
else {// OTHER MODES
if (drawWireFrames==1) DogaSetPixel(i,j,z,color(R,G,B,W)); 
else {
DogaSetPixel(i,j,z,color(R*m,G*m,B*m,W)); 
DogaSetPixel(i,j-1,z,color(R*(1-m),G*(1-m),B*(1-m),W)); 
}
}
z+=zDif;
}
}
}
void drawDogaLineCOL(int x0,int y0,float z0,int x1,int y1,float z1,color c) {
int xs,xf,ys,yf;
float zs=0,zf=0,zDif=0,z=0;
int i,j,k,d=1;
// first lets make sure that xf>xs
if (x1>x0) {xs=x0;xf=x1;ys=y0;yf=y1;zs=z0;zf=z1;}
else {xs=x1;xf=x0;ys=y1;yf=y0;zs=z1;zf=z0;}
if (yf<ys) d=-1;

int dx=xf-xs;
int dy=(yf-ys)*d;
int dif=dy-dx;

stroke(c);    
point(xs,ys);  
if (dx>=dy) { // IF X-BASED
i=xs;j=ys;zDif=(zf-zs)/dx;z=zs;
while (i!=xf) {
if (dif>0) {i++;j+=d;dif+=dy-dx;}
else {i++;dif+=dy;}
if (drawMode==0) point(i,j); //simple mode
else DogaSetPixel(i,j,z,c);// zBufferMode or triangulateMode
z+=zDif;
}
}
else { // IF Y-BASED
i=xs;j=ys;zDif=(zf-zs)/dy;z=zs;
while (j!=yf) {
if (dif>0) {i++;j+=d;dif+=dx-dy;}
else {j+=d;dif+=dx;}
if (drawMode==0) point(i,j);//simple mode 
else DogaSetPixel(i,j,z,c);// zBufferMode or triangulateMode
z+=zDif;
}
}
}
//FOR FLOATING POINT ABSOLUTE VALUE :)
float absD(float x) {
if (x>=0) return x;
return -x;
}
//FOR DEBUGGING PURPOSES
void PrintPoints(String name,float p[][],int row,int col) {
int i=0,j=0;
println("Printing "+name);
for (i=0;i<row;i++) {
print("  ");
for(j=0;j<col;j++)
print("["+p[i][j]+"],");
println();
}
}
void readInEachSff() {
int i=0,j=0,k=0,cnt=0;
String sff[];
nMesh = new int[nSff];
nV = new int[nSff][];
for(i=0;i<nSff;i++){
cnt=0;
sff = loadStrings(sffName[i]);
nMesh[i] = int(sff[cnt++]);
objectS[i] = new float[nMesh[i]][][];
objectD[i] = new float[nMesh[i]][][];
nV[i] = new int[nMesh[i]];
DogaRotateFX(rx[i],ry[i],rz[i]);
DogaScaleFX(sx[i],sy[i],sz[i]);
DogaTranslateFX(tx[i],ty[i],tz[i]);
meshTextArea[i] = new int[nMesh[i]][];
for (j=0;j<nMesh[i];j++) {
nV[i][j] = int(trim(sff[cnt++]));
meshTextArea[i][j] = new int[3];
objectS[i][j] = new float[nV[i][j]][4];
objectD[i][j] = new float[nV[i][j]][4];
for (k=0;k<nV[i][j];k++) {// now read every point in mesh
line1 = split(trim(sff[cnt++]),' ');
objectS[i][j][k][0] = float(line1[0]);
objectS[i][j][k][1] = float(line1[1]);
objectS[i][j][k][2] = float(line1[2]);
objectS[i][j][k][3] = 1;
}//k-nV
}//j-nMesh
ApplyMatrix(i);
}//i-nSff 
}
void readInSffs(){
int i=0,n=nSff;
r = new int[n]; g = new int[n]; b = new int[n];
rx = new float[n]; ry = new float[n]; rz = new float[n];
sx = new float[n]; sy = new float[n]; sz = new float[n];
tx = new float[n]; ty = new float[n]; tz = new float[n];
sffName = new String[n];
for (i=0;i<n;i++){
line1 = split(data[i+3],' ');
r[i] = int(line1[0]);
g[i] = int(line1[1]);
b[i] = int(line1[2]);
rx[i] = float(line1[3]);ry[i]=float(line1[4]);rz[i] = float(line1[5]);
sx[i] = float(line1[6]);sy[i]=float(line1[7]);sz[i] = float(line1[8]);
tx[i] = float(line1[9]);ty[i]=float(line1[10]);tz[i] = float(line1[11]);
sffName[i] = line1[12];
projectionMode[i]=1;
}
readInEachSff();
}
void readInBasicFile(){
int i=0;
data = loadStrings(fileName[activeFile]);
nSff=data.length-3;
objectS = new float[nSff][][][];
objectD = new float[nSff][][][];
meshTextArea = new int[nSff][][];
projectionMode = new int[nSff]; 
line1 = split(data[0],' ');
xRes=int(line1[0]); yRes=int(line1[1]);
zBuf = new int[xRes][yRes];
cBuf = new color[xRes][yRes];
line1 = split(data[1],' ');
pM = new float[4];uM = new float[4];vM = new float[4];nM = new float[4];
pM[0]=float(line1[0]);pM[1]=float(line1[1]); pM[2]=float(line1[2]);pM[3]=1;
uM[0]=float(line1[3]);uM[1]=float(line1[4]); uM[2]=float(line1[5]);uM[3]=1;
vM[0]=float(line1[6]);vM[1]=float(line1[7]); vM[2]=float(line1[8]);vM[3]=1;
nM[0]=float(line1[9]);nM[1]=float(line1[10]);nM[2]=float(line1[11]);nM[3]=1;
DogaCameraFX(pM,uM,vM,nM);
line1 = split(data[2],' ');
near = float(line1[0]);  far = float(line1[1]);
top = float(line1[2]);  bottom = float(line1[3]);
left = float(line1[4]); right = float(line1[5]);
DogaProjectionFX(1,near,far,top,bottom,left,right);
readInSffs();
}
int fI=33,mI=7;//FIRST INDEX
void setTextAreaValues() {
int i=0,j=0;
textArea = new int[41][4];
for (i=0;i<14;i++) {
textArea[i][0]=int(width*0.75);
textArea[i][1]=width;
textArea[i][2]=j;
textArea[i][3]=j+20;
j+=20;
}
j=0;
for (i=14;i<30;i++) {
textArea[i][0]=0;
textArea[i][1]=int(width*0.27);
textArea[i][2]=j;
textArea[i][3]=j+20;
j+=20;
}
j=height-(mI+2)*20;
for (i=fI;i<=fI+mI;i++) {
textArea[i][0]=0;
textArea[i][1]=int(width-1);
textArea[i][2]=j;
textArea[i][3]=j+20;
j+=20;
}
}
void drawText() {
fill(0,255,0);
//First the object selected will be mentioned
text("Object->"+sffName[selectedObject],textArea[0][0],textArea[0][3]);
//Second projectionMode
if (projectionMode[selectedObject]==1) text("ProjMode->Perspective",textArea[1][0],textArea[1][3]);
else  text("ProjMode->Orthogonal",textArea[1][0],textArea[1][3]);

text("Rotation Values->",textArea[2][0],textArea[2][3]);
text("Rx=("+rx[selectedObject]+")",textArea[3][0],textArea[3][3]);
text("Ry=("+ry[selectedObject]+")",textArea[4][0],textArea[4][3]);
text("Rz=("+rz[selectedObject]+")",textArea[5][0],textArea[5][3]);

text("Scale Values->",textArea[6][0],textArea[6][3]);
text("Sx=("+sx[selectedObject]+")",textArea[7][0],textArea[7][3]);
text("Sy=("+sy[selectedObject]+")",textArea[8][0],textArea[8][3]);
text("Sz=("+sz[selectedObject]+")",textArea[9][0],textArea[9][3]);

text("Translate Values->",textArea[10][0],textArea[10][3]);
text("Tx=("+tx[selectedObject]+")",textArea[11][0],textArea[11][3]);
text("Ty=("+ty[selectedObject]+")",textArea[12][0],textArea[12][3]);
text("Tz=("+tz[selectedObject]+")",textArea[13][0],textArea[13][3]);

text("File->"+fileName[activeFile],textArea[14][0],textArea[14][3]);

fill(255,255,255);
text("click on any text in screen.",textArea[14][1]+width*0.1,textArea[14][3]);
text("then press + and - to change values.",textArea[14][1]+width*0.05,textArea[15][3]);
fill(0,255,0);

text("Camera Values->",textArea[15][0],textArea[15][3]);

text("Px=("+pM[0]+")",textArea[16][0],textArea[16][3]);
text("Py=("+pM[1]+")",textArea[17][0],textArea[17][3]);
text("Pz=("+pM[2]+")",textArea[18][0],textArea[18][3]);

text("Ux=("+uM[0]+")",textArea[19][0],textArea[19][3]);
text("Uy=("+uM[1]+")",textArea[20][0],textArea[20][3]);
text("Uz=("+uM[2]+")",textArea[21][0],textArea[21][3]);

text("Vx=("+vM[0]+")",textArea[22][0],textArea[22][3]);
text("Vy=("+vM[1]+")",textArea[23][0],textArea[23][3]);
text("Vz=("+vM[2]+")",textArea[24][0],textArea[24][3]);

text("Nx=("+nM[0]+")",textArea[25][0],textArea[25][3]);
text("Ny=("+nM[1]+")",textArea[26][0],textArea[26][3]);
text("Nz=("+nM[2]+")",textArea[27][0],textArea[27][3]);

if (drawWireFrames==0) text("Not Drawing Wires.",textArea[28][0],textArea[28][3]);
else if (drawWireFrames==1) text("Drawing Jaggy-W.",textArea[28][0],textArea[28][3]);
else if (drawWireFrames==2) text("Drawing Anti-Aliased-W.",textArea[28][0],textArea[28][3]);

if (showLightSources) text("Show Active Lights.",textArea[29][0],textArea[29][3]);
else text("Dont Show Active Lights.",textArea[29][0],textArea[29][3]);

fill(90+time/2,90+time/2,0);
if (warningText!=null) text(warningText,textArea[fI+mI-6][0],textArea[fI+mI-6][3]);    

fill(255,255,255);
if (drawMode==0) text("Drawing in simple mode.(Click to change mode)",textArea[fI+mI-5][0],textArea[fI+mI-5][3]);
if (drawMode==1) text("Drawing in Z-Buffer mode.(Click to change mode)",textArea[fI+mI-5][0],textArea[fI+mI-5][3]);
if ((drawMode==2)&&(numDisplay)) text("Drawing in back-face culling mode.(Click to change mode or press 'n-N' to deactivate numbers)",textArea[fI+mI-5][0],textArea[fI+mI-5][3]);
if ((drawMode==2)&&(!numDisplay)) text("Drawing in back-face culling mode.(Click to change mode or press 'n-N' to activate numbers)",textArea[fI+mI-5][0],textArea[fI+mI-5][3]);
if ((drawMode==3)&&(numDisplay)) text("Drawing in lighting mode.(Click to change mode or press 'n-N' to deactivate numbers)",textArea[fI+mI-5][0],textArea[fI+mI-5][3]);
if ((drawMode==3)&&(!numDisplay)) text("Drawing in lighting mode.(Click to change mode or press 'n-N' to activate numbers)",textArea[fI+mI-5][0],textArea[fI+mI-5][3]);

if (((drawMode==2)||(drawMode==3))&&(numDisplay)) {
stroke(0,255,0);
for (int j=0;j<nMesh[selectedObject];j++)
if (meshTextArea[selectedObject][j][2]>0)
text(j,meshTextArea[selectedObject][j][0],meshTextArea[selectedObject][j][1]);
}

if (ActiveLights[selectedLight]==1) {
if (drawMode!=3) text("Light_"+selectedLight+" is on.Click 'L-l' to turn off the light.(To see effects switch to lighting mode)",textArea[fI+mI-4][0],textArea[fI+mI-4][3]);
else text("Light_"+selectedLight+" is on.Click 'L-l' to turn off the light.(To move the light press 'm or M'.)",textArea[fI+mI-4][0],textArea[fI+mI-4][3]);

fill(Light[selectedLight][AMBIENTi][Ri],Light[selectedLight][AMBIENTi][Gi],Light[selectedLight][AMBIENTi][Bi],100+Light[selectedLight][AMBIENTi][Wi]);
if (moveLight) {
fill(30,30,30);     
if (AMBIENTon[selectedLight])
text("To control these values press 'm or M' again.]Amb.R="+Light[selectedLight][AMBIENTi][Ri]+
"/ Amb.G="+Light[selectedLight][AMBIENTi][Gi]+
"/ Amb.B="+Light[selectedLight][AMBIENTi][Bi]+
"/ Amb.W="+Light[selectedLight][AMBIENTi][Wi],textArea[fI+mI-3][0],textArea[fI+mI-3][3]);
else text("AMBIENT off.(press 'a or A' to turn it on)",textArea[fI+mI-3][0],textArea[fI+mI-3][3]);
}
else {
if (AMBIENTon[selectedLight])
text("Amb.R="+Light[selectedLight][AMBIENTi][Ri]+
"/ Amb.G="+Light[selectedLight][AMBIENTi][Gi]+
"/ Amb.B="+Light[selectedLight][AMBIENTi][Bi]+
"/ Amb.W="+Light[selectedLight][AMBIENTi][Wi]+"(press 'a or A' to turn it off)",textArea[fI+mI-3][0],textArea[fI+mI-3][3]);
else text("AMBIENT off.(press 'a or A' to turn it on)",textArea[fI+mI-3][0],textArea[fI+mI-3][3]);
}
fill(Light[selectedLight][DIFFUSEi][Ri],Light[selectedLight][DIFFUSEi][Gi],Light[selectedLight][DIFFUSEi][Bi],100+Light[selectedLight][DIFFUSEi][Wi]);
if (moveLight) {      
fill(30,30,30);     
if (DIFFUSEon[selectedLight])
text("To control these values press 'm or M' again.]Dif.R="+Light[selectedLight][DIFFUSEi][Ri]+
"/ Dif.G="+Light[selectedLight][DIFFUSEi][Gi]+
"/ Dif.B="+Light[selectedLight][DIFFUSEi][Bi]+
"/ Dif.W="+Light[selectedLight][DIFFUSEi][Wi],textArea[fI+mI-2][0],textArea[fI+mI-2][3]);
else text("DIFFUSE off.",textArea[fI+mI-2][0],textArea[fI+mI-2][3]);
}
else {
if (DIFFUSEon[selectedLight])
text("Dif.R="+Light[selectedLight][DIFFUSEi][Ri]+
"/ Dif.G="+Light[selectedLight][DIFFUSEi][Gi]+
"/ Dif.B="+Light[selectedLight][DIFFUSEi][Bi]+
"/ Dif.W="+Light[selectedLight][DIFFUSEi][Wi]+"(press 'd or D' to turn it off)",textArea[fI+mI-2][0],textArea[fI+mI-2][3]);
else text("DIFFUSE off.(press 'd or D' to turn it on)",textArea[fI+mI-2][0],textArea[fI+mI-2][3]);
}

fill(Light[selectedLight][SPECULARi][Ri],Light[selectedLight][SPECULARi][Gi],Light[selectedLight][SPECULARi][Bi],255);
if (moveLight) {
fill(30,30,30);     
if (SPECULARon[selectedLight])
text("To control these values press 'm or M' again.]Spc.R="+Light[selectedLight][SPECULARi][Ri]+
"/ Spc.G="+Light[selectedLight][SPECULARi][Gi]+
"/ Spc.B="+Light[selectedLight][SPECULARi][Bi]+
"/ Spc.n="+(1+20*(Light[selectedLight][SPECULARi][Wi]/255)),textArea[fI+mI-1][0],textArea[fI+mI-1][3]);
else text("SPECULAR off.",textArea[fI+mI-1][0],textArea[fI+mI-1][3]);
}
else { 
if (SPECULARon[selectedLight])
text("Spc.R="+Light[selectedLight][SPECULARi][Ri]+
"/ Spc.G="+Light[selectedLight][SPECULARi][Gi]+
"/ Spc.B="+Light[selectedLight][SPECULARi][Bi]+
"/ Spc.n="+(1+20*(Light[selectedLight][SPECULARi][Wi]/255))+"(press 's or S' to turn it off)",textArea[fI+mI-1][0],textArea[fI+mI-1][3]);
else text("SPECULAR off.(press 's or S' to turn it on)",textArea[fI+mI-1][0],textArea[fI+mI-1][3]);
}
fill(0,255,0);
text("Lx="+Light[selectedLight][POSITIONi][Xi]+
"/ Ly="+Light[selectedLight][POSITIONi][Yi]+
"/ Lz="+Light[selectedLight][POSITIONi][Zi],textArea[fI+mI-0][0],textArea[fI+mI-0][3]);
}
else {
if (drawMode!=3) text("Light_"+selectedLight+" is off.Click 'L-l' to turn on the light.(To see effects turn light on & switch to lighting mode)",textArea[fI+mI-4][0],textArea[fI+mI-4][3]);
else text("Light_"+selectedLight+" is off.Click 'L-l' to turn on the light.(To see effects you need to turn at least 1 light on.)",textArea[fI+mI-4][0],textArea[fI+mI-4][3]);
}
drawTextAreas();
}
void drawTextAreas() {
int i=0,j=0;
stroke(25,75,125);
noFill();
rectMode(CORNERS);
for (i=0;i<30;i++)
rect(textArea[i][0],textArea[i][2],textArea[i][1],textArea[i][3]);
for (i=fI+1;i<fI+mI+1;i++)
rect(textArea[i][0],textArea[i][2],textArea[i][1],textArea[i][3]);
}
void keyPressed() {
int i=0;
if (key=='0') drawMode=0;
else if (key=='1') drawMode=1;
else if (key=='2') drawMode=2;
else if (key=='3') drawMode=3;
else if ((key=='4')&&(fillR<255)) {fillR++;fillG++;fillB++;}
else if ((key=='5')&&(fillR>0)) {fillR--;fillG--;fillB--;}

if ((key=='0')&&(key=='1')&&(key=='2')&&(key=='3')) {
if (drawMode==2) {time=0; timeIncrease=true; timeInc = 25;}
else if (drawMode==3) {time=0; timeIncrease=true; timeInc = 51;}
else timeInc = 5;
}

if (moveLight) {
if (((key=='w')||(key=='W'))&&(Light[selectedLight][POSITIONi][Yi]>0)) Light[selectedLight][POSITIONi][Yi]-=1;
if (((key=='a')||(key=='A'))&&(Light[selectedLight][POSITIONi][Xi]>0)) Light[selectedLight][POSITIONi][Xi]-=1;
if (((key=='s')||(key=='S'))&&(Light[selectedLight][POSITIONi][Yi]<height)) Light[selectedLight][POSITIONi][Yi]+=1;
if (((key=='d')||(key=='D'))&&(Light[selectedLight][POSITIONi][Xi]<width)) Light[selectedLight][POSITIONi][Xi]+=1;
if ((key=='q')||(key=='Q')) Light[selectedLight][POSITIONi][Zi]+=1;
if ((key=='e')||(key=='E')) Light[selectedLight][POSITIONi][Zi]-=1;
}
else if ((key=='a')||(key=='A')) AMBIENTon[selectedLight]=!AMBIENTon[selectedLight];
else if ((key=='d')||(key=='D')) DIFFUSEon[selectedLight]=!DIFFUSEon[selectedLight];
else if ((key=='s')||(key=='S')) SPECULARon[selectedLight]=!SPECULARon[selectedLight];
else if ((key=='r')||(key=='R')) selectedColor=0;
else if ((key=='g')||(key=='G')) selectedColor=1;
else if ((key=='b')||(key=='B')) selectedColor=2;
else if ((key=='w')||(key=='W')) selectedColor=3;
if ((key=='n')||(key=='N')) numDisplay=!numDisplay;
if (((key=='m')||(key=='M'))&&(ActiveLights[selectedLight]==1)) moveLight = !moveLight;  
else if ((key=='l')||(key=='L')) {
if (ActiveLights[selectedLight]==1) {
ActiveLights[selectedLight] = 0;
numOfActiveLights--;
}
else {
ActiveLights[selectedLight] = 1;
numOfActiveLights++;
}    
}
if (key=='+') {
if (selectedTextArea==0) selectedObject = (selectedObject+1)%nSff;
if (selectedTextArea==1) {
projectionMode[selectedObject]=(projectionMode[selectedObject]+1)%2;
DogaProjectionFX(projectionMode[selectedObject],near,far,top,bottom,left,right);
}
if (selectedTextArea==2) {
rx[selectedObject]+=0.05;
if (rx[selectedObject]>6.28) rx[selectedObject]-=6.28;
ry[selectedObject]+=0.05;
if (ry[selectedObject]>6.28) ry[selectedObject]-=6.28;
rz[selectedObject]+=0.05;
if (rz[selectedObject]>6.28) rz[selectedObject]-=6.28;
}
if (selectedTextArea==3) {
rx[selectedObject]+=0.05;
if (rx[selectedObject]>6.28) rx[selectedObject]-=6.28;
}
if (selectedTextArea==4) {
ry[selectedObject]+=0.05;
if (ry[selectedObject]>6.28) ry[selectedObject]-=6.28;
}
if (selectedTextArea==5) {
rz[selectedObject]+=0.05;
if (rz[selectedObject]>6.28) rz[selectedObject]-=6.28;
}
if (selectedTextArea==6) {
sx[selectedObject]+=0.05;
sy[selectedObject]+=0.05;
sz[selectedObject]+=0.05;
}
if (selectedTextArea==7) {
sx[selectedObject]+=0.05;
}
if (selectedTextArea==8) {
sy[selectedObject]+=0.05;
}
if (selectedTextArea==9) {
sz[selectedObject]+=0.05;
}
if (selectedTextArea==10) {
tx[selectedObject]+=0.05;
ty[selectedObject]+=0.05;
tz[selectedObject]+=0.05;
}
if (selectedTextArea==11) {
tx[selectedObject]+=0.05;
}
if (selectedTextArea==12) {
ty[selectedObject]+=0.05;
}
if (selectedTextArea==13) {
tz[selectedObject]+=0.05;
}
if ((selectedTextArea>0)&&(selectedTextArea<14)) ApplyMatrix(selectedObject);
if (selectedTextArea==14){
activeFile=(activeFile+1)%nFile;
readInBasicFile();  
size(xRes,yRes);
selectedObject=0;
}
if (selectedTextArea==16) pM[0]+=0.01;
if (selectedTextArea==17) pM[1]+=0.01;
if (selectedTextArea==18) pM[2]+=0.01;
if (selectedTextArea==19) uM[0]+=0.01;
if (selectedTextArea==20) uM[1]+=0.01;
if (selectedTextArea==21) uM[2]+=0.01;
if (selectedTextArea==22) vM[0]+=0.01;
if (selectedTextArea==23) vM[1]+=0.01;
if (selectedTextArea==24) vM[2]+=0.01;
if (selectedTextArea==25) nM[0]+=0.01;
if (selectedTextArea==26) nM[1]+=0.01;
if (selectedTextArea==27) nM[2]+=0.01;
if ((selectedTextArea>14)&&(selectedTextArea<28)) {
DogaCameraFX(pM,uM,vM,nM);
for(i=0;i<nSff;i++) ApplyMatrix(i);
}
if (selectedTextArea==28) drawWireFrames=(drawWireFrames+1)%3;
if (selectedTextArea==29) showLightSources=!showLightSources;

if (selectedTextArea==fI+mI-5) drawMode = (drawMode+1)%4;
if (selectedTextArea==fI+mI-4) selectedLight = (selectedLight+1)%numOfLights;
if ((selectedTextArea==fI+mI-3)&&(Light[selectedLight][AMBIENTi][selectedColor]<255)) Light[selectedLight][AMBIENTi][selectedColor]+=3;
if ((selectedTextArea==fI+mI-2)&&(Light[selectedLight][DIFFUSEi][selectedColor]<255)) Light[selectedLight][DIFFUSEi][selectedColor]+=3;
if ((selectedTextArea==fI+mI-1)&&(Light[selectedLight][SPECULARi][selectedColor]<255)) Light[selectedLight][SPECULARi][selectedColor]+=3;
}
else if (key=='-') {
if (selectedTextArea==0) selectedObject = (selectedObject-1)%nSff;
if (selectedTextArea==1) {
projectionMode[selectedObject]=(projectionMode[selectedObject]-1)%2;
DogaProjectionFX(projectionMode[selectedObject],near,far,top,bottom,left,right);
}
if (selectedTextArea==2) {
rx[selectedObject]-=0.05;
if (rx[selectedObject]<0) rx[selectedObject]+=6.28;
ry[selectedObject]-=0.05;
if (ry[selectedObject]<0) ry[selectedObject]+=6.28;
rz[selectedObject]-=0.05;
if (rz[selectedObject]<0) rz[selectedObject]+=6.28;
}
if (selectedTextArea==3) {
rx[selectedObject]-=0.05;
if (rx[selectedObject]<0) rx[selectedObject]+=6.28;
}
if (selectedTextArea==4) {
ry[selectedObject]-=0.05;
if (ry[selectedObject]<0) ry[selectedObject]+=6.28;
}
if (selectedTextArea==5) {
rz[selectedObject]-=0.05;
if (rz[selectedObject]<0) rz[selectedObject]+=6.28;
}
if (selectedTextArea==6) {
if (sx[selectedObject]>0.05) sx[selectedObject]-=0.05;
if (sy[selectedObject]>0.05) sy[selectedObject]-=0.05;
if (sz[selectedObject]>0.05) sz[selectedObject]-=0.05;
}
if (selectedTextArea==7) {
if (sx[selectedObject]>0.05) sx[selectedObject]-=0.05;
}
if (selectedTextArea==8) {
if (sy[selectedObject]>0.05) sy[selectedObject]-=0.05;
}
if (selectedTextArea==9) {
if (sz[selectedObject]>0.05) sz[selectedObject]-=0.05;
}
if (selectedTextArea==10) {
tx[selectedObject]-=0.05;
ty[selectedObject]-=0.05;
tz[selectedObject]-=0.05;
}
if (selectedTextArea==11) {
tx[selectedObject]-=0.05;
}
if (selectedTextArea==12) {
ty[selectedObject]-=0.05;
}
if (selectedTextArea==13) {
tz[selectedObject]-=0.05;
}
if ((selectedTextArea>0)&&(selectedTextArea<14)) ApplyMatrix(selectedObject);
if (selectedTextArea==16) pM[0]-=0.01;
if (selectedTextArea==17) pM[1]-=0.01;
if (selectedTextArea==18) pM[2]-=0.01;
if (selectedTextArea==19) uM[0]-=0.01;
if (selectedTextArea==20) uM[1]-=0.01;
if (selectedTextArea==21) uM[2]-=0.01;
if (selectedTextArea==22) vM[0]-=0.01;
if (selectedTextArea==23) vM[1]-=0.01;
if (selectedTextArea==24) vM[2]-=0.01;
if (selectedTextArea==25) nM[0]-=0.01;
if (selectedTextArea==26) nM[1]-=0.01;
if (selectedTextArea==27) nM[2]-=0.01;
if ((selectedTextArea>14)&&(selectedTextArea<28)) {
DogaCameraFX(pM,uM,vM,nM);
for(i=0;i<nSff;i++) ApplyMatrix(i);
}
if (selectedTextArea==28) drawWireFrames=(drawWireFrames+2)%3;
if (selectedTextArea==29) showLightSources=!showLightSources;

if (selectedTextArea==fI+mI-5) drawMode = (drawMode-1+4)%4;
if (selectedTextArea==fI+mI-4) selectedLight = (selectedLight-1+numOfLights)%numOfLights;
if ((selectedTextArea==fI+mI-3)&&(Light[selectedLight][AMBIENTi][selectedColor]>0)) Light[selectedLight][AMBIENTi][selectedColor]-=3;
if ((selectedTextArea==fI+mI-2)&&(Light[selectedLight][DIFFUSEi][selectedColor]>0)) Light[selectedLight][DIFFUSEi][selectedColor]-=3;
if ((selectedTextArea==fI+mI-1)&&(Light[selectedLight][SPECULARi][selectedColor]>0)) Light[selectedLight][SPECULARi][selectedColor]-=3;
}
endControl();
}
void mousePressed() {
selectedTextArea=-1;
if ((mouseX>textArea[0][0])&&(mouseY<=textArea[13][3])) selectedTextArea = (int)(mouseY-(mouseY%20))/20; //TEXTS ON THE RIGHT SIDE
else if ((mouseX<=textArea[14][1])&&(mouseY<=textArea[29][3])) selectedTextArea = 14+(int)(mouseY-(mouseY%20))/20; //TEXTS ON THE LEFT UPPER SIDE
else if (mouseY>=textArea[fI][2]) selectedTextArea = fI+(int)(mouseY-textArea[fI][2]-(mouseY%20))/20; // TEXT ON THE DOWN SIDE

if (selectedTextArea==0) selectedObject = (selectedObject+1)%nSff;
else if (selectedTextArea==1) {
projectionMode[selectedObject]=(projectionMode[selectedObject]+1)%2;
DogaProjectionFX(projectionMode[selectedObject],near,far,top,bottom,left,right);
ApplyMatrix(selectedObject);
}
else if (selectedTextArea==14){
activeFile=(activeFile+1)%nFile;
readInBasicFile();  
size(xRes,yRes);
selectedObject=0;
}
//WIREFRAME DRAWING SETUP
else if (selectedTextArea==28) {
if (drawMode<3) drawWireFrames=(drawWireFrames+1)%3;
else drawWireFrames=(drawWireFrames+1)%2;
}
else if (selectedTextArea==29) showLightSources=!showLightSources;  
else if (selectedTextArea==fI+mI-5) {
drawMode=(drawMode+1)%4;
if (drawMode>1) {time=0; timeIncrease=true; timeInc = 51;}
else timeInc = 5;
}
else if (selectedTextArea==fI+mI-4) {
selectedLight=(selectedLight+1)%numOfLights;
moveLight = false;
}
endControl();
}
void endControl() {
if (drawMode!=3) warningText = new String("To see light-effects switch to lighting mode.[Click the text below or press '3']");
else if (numOfActiveLights==0) warningText = new String("(To see light-effects you have to activate at least 1 light).");
else if (ActiveLights[selectedLight]==1) {
if (moveLight) warningText = new String("You are moving the light.Use w,a,s,d,q,e to move the light.Then click m.");
else warningText = new String("Click on light type.Then press r,g,b,w then press '+ or -' to change the light values.");
}
else warningText = new String("You have another active light but not this one. To control it click on 'Light_'");

if ((drawMode<3)&&(drawWireFrames==0)) drawWireFrames=1;
else if ((drawMode==3)&&(drawWireFrames==2)) drawWireFrames=0;
}

			</p>
			
			<p>
			Source code: <a href="P019_WIRES_LIGHTING.pde">P019_WIRES_LIGHTING</a> 
			</p>
			
			<p>
			Built with <a href="http://processing.org" title="Processing.org">Processing</a>
			</p>
		</div>
	</body>
</html>
